package com.android.inputmethod.pinyin;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.util.Log;

import com.upu173.pinyinime.R;

import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * This class is used to separate the input method kernel in an individual
 * service so that both IME and IME-syncer can use it.
 */
public class PinyinDecoderService {

    private Context context;

    native static boolean nativeImOpenDecoder(byte fn_sys_dict[], byte fn_usr_dict[]);
    native static boolean nativeImOpenDecoderFd(FileDescriptor fd, long startOffset, long length,byte fn_usr_dict[]);

    native static void nativeImSetMaxLens(int maxSpsLen, int maxHzsLen);
    native static boolean nativeImCloseDecoder();

    native static int nativeImSearch(byte pyBuf[], int pyLen);
    native static int nativeImDelSearch(int pos, boolean is_pos_in_splid,boolean clear_fixed_this_step);
    native static void nativeImResetSearch();

    native static int nativeImAddLetter(byte ch);
    native static String nativeImGetPyStr(boolean decoded);
    native static int nativeImGetPyStrLen(boolean decoded);
    native static int[] nativeImGetSplStart();
    native static String nativeImGetChoice(int choiceId);
    native static int nativeImChoose(int choiceId);
    native static int nativeImCancelLastChoice();
    native static int nativeImGetFixedLen();
    native static boolean nativeImCancelInput();
    native static boolean nativeImFlushCache();

    native static int nativeImGetPredictsNum(String fixedStr);
    native static String nativeImGetPredictItem(int predictNo);

    native static String nativeSyncUserDict(byte[] user_dict, String tomerge);
    native static boolean nativeSyncBegin(byte[] user_dict);
    native static boolean nativeSyncFinish();
    native static String nativeSyncGetLemmas();
    native static int nativeSyncPutLemmas(String tomerge);
    native static int nativeSyncGetLastCount();
    native static int nativeSyncGetTotalCount();
    native static boolean nativeSyncClearLastGot();
    native static int nativeSyncGetCapacity();

    private final static int MAX_PATH_FILE_LENGTH = 100;
    private static boolean inited = false;

    private String mUsr_dict_file;

    public PinyinDecoderService(Context context) {
        this.context = context;
        init();

    }

    static {
        try {
            System.loadLibrary("jni_pinyinime");
        } catch (UnsatisfiedLinkError ule) {
            Log.e("PinyinDecoderService", "SO库加载失败:libpinyinime.so");
        }
    }

    private boolean getUsrDictFileName(byte usr_dict[]) {
        if (null == usr_dict) {
            return false;
        }

        for (int i = 0; i < mUsr_dict_file.length(); i++)
            usr_dict[i] = (byte) mUsr_dict_file.charAt(i);
        usr_dict[mUsr_dict_file.length()] = 0;

        return true;
    }

    private void initPinyinEngine() {
        byte usr_dict[];
        usr_dict = new byte[MAX_PATH_FILE_LENGTH];
        //dict_pinyin 不是图片，是dat文件  后缀被我改成了png  不然openRawResourceFd会不支持打开
        AssetFileDescriptor afd = context.getResources().openRawResourceFd(R.raw.dict_pinyin);
        Log.i("foo", "Dict: start="
                + afd.getStartOffset()
                + ", length="
                + afd.getLength()
                + ", fd="
                + afd.getParcelFileDescriptor());
        if (getUsrDictFileName(usr_dict)) {
            inited = nativeImOpenDecoderFd(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(),
                    usr_dict);
        }
        try {
            afd.close();
        } catch (IOException e) {
        }
    }

    public void init() {
        // 获取用户词典"usr_dict.dat"的路径。"usr_dict.dat"放在file目录下。
        // 猜测：调用getFileStreamPath("usr_dict.dat")，如果"usr_dict.dat"不存在，会调用openFileOutput（）创建该文件。
        mUsr_dict_file = context.getFileStreamPath("usr_dict.dat").getPath();
        try {
            context.openFileOutput("dummy", 0).close();
        } catch (Exception e) {
        }

        initPinyinEngine();
    }

    public void closeDecoder() {
        nativeImCloseDecoder();
        inited = false;
    }


    /**
     * 设置最大的长度
     */
    public void setMaxLens(int maxSpsLen, int maxHzsLen) {
        nativeImSetMaxLens(maxSpsLen, maxHzsLen);
    }

    /**
     * 根据拼音查询候选词
     * @param pyBuf
     * @return 候选词数量
     */
    public int imSearch(byte[] pyBuf) {
        return nativeImSearch(pyBuf, pyBuf.length);
    }

    /**
     * 删除指定位置的拼音后进行查询
     */
    public int imDelSearch(int pos, boolean is_pos_in_splid,boolean clear_fixed_this_step) {
        return nativeImDelSearch(pos, is_pos_in_splid,clear_fixed_this_step);
    }

    /**
     * 重置拼音查询，应该是清除之前查询的数据
     */
    public void imResetSearch() {
        nativeImResetSearch();
    }

    /**
     * 增加字母
     */
    public int imAddLetter(byte ch) {
        return nativeImAddLetter(ch);
    }

    /**
     * 获取拼音字符串
     */
    public String imGetPyStr(boolean decoded) {
        return nativeImGetPyStr(decoded);
    }

    /**
     * 获取拼音字符串的长度
     */
    public int imGetPyStrLen(boolean decoded) {
        return nativeImGetPyStrLen(decoded);
    }

    /**
     * 获取每个拼写的开始位置，猜测：第一个元素是拼写的总数量
     */
    public int[] imGetSplStart() {
        return nativeImGetSplStart();
    }

    /**
     * 获取指定位置的候选词
     */
    public String imGetChoice(int index) {
        return nativeImGetChoice(index);
    }

    /**
     * 获取多个候选词
     */
    public List<String> imGetChoices(int count) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < count; i++) {
                list.add(nativeImGetChoice(i));
        }
        return list;
    }

    /**
     * 获取候选词的数量
     */
    public int imChoose(int choiceId) {
        return nativeImChoose(choiceId);
    }

    /**
     * 取消最后的选择
     */
    public int imCancelLastChoice() {
        return nativeImCancelLastChoice();
    }

    /**
     * 获取固定字符的长度
     */
    public int imGetFixedLen() {
        return nativeImGetFixedLen();
    }

    /**
     * 取消输入
     */
    public boolean imCancelInput() {
        return nativeImCancelInput();
    }

    /**
     * 刷新缓存
     */
    public void imFlushCache() {
        nativeImFlushCache();
    }

    /**
     * 根据字符串 fixedStr 获取预报的候选词
     */
    public int imGetPredictsNum(String fixedStr) {
        return nativeImGetPredictsNum(fixedStr);
    }

    /**
     * 获取指定位置的预报候选词
     */
    public String imGetPredictItem(int predictNo) {
        return nativeImGetPredictItem(predictNo);
    }

    /**
     * 获取候选词列表
     */
    public List<String> imGetPredictList(int predictsStart, int predictsNum) {
        Vector<String> predictList = new Vector<String>();
        for (int i = predictsStart; i < predictsStart + predictsNum; i++) {
            predictList.add(nativeImGetPredictItem(i));
        }
        return predictList;
    }

    /**
     * 同步到用户词典，猜测：是不是记住用户的常用词。
     */
    public String syncUserDict(String tomerge) {
        byte usr_dict[];
        usr_dict = new byte[MAX_PATH_FILE_LENGTH];

        if (getUsrDictFileName(usr_dict)) {
            return nativeSyncUserDict(usr_dict, tomerge);
        }
        return null;
    }

    /**
     * 开始用户词典同步
     */
    public boolean syncBegin() {
        byte usr_dict[];
        usr_dict = new byte[MAX_PATH_FILE_LENGTH];

        if (getUsrDictFileName(usr_dict)) {
            return nativeSyncBegin(usr_dict);
        }
        return false;
    }

    /**
     * 同步结束
     */
    public void syncFinish() {
        nativeSyncFinish();
    }

    /**
     * 同步存入Lemmas
     */
    public int syncPutLemmas(String tomerge) {
        return nativeSyncPutLemmas(tomerge);
    }

    /**
     * 同步获取Lemmas
     */
    public String syncGetLemmas() {
        return nativeSyncGetLemmas();
    }

    /**
     * 同步获取最后的数量
     */
    public int syncGetLastCount() {
        return nativeSyncGetLastCount();
    }

    /**
     * 同步获取总数量
     */
    public int syncGetTotalCount() {
        return nativeSyncGetTotalCount();
    }

    /**
     * 同步清空最后获取
     */
    public void syncClearLastGot() {
        nativeSyncClearLastGot();
    }

    /**
     * 同步获取容量
     */
    public int imSyncGetCapacity() {
        return nativeSyncGetCapacity();
    }

}
